﻿/*
 Wrap Interface of Kinect2 SDK
 According to MS Kinect SDK Vesrion 2.0.1410.19000

 Date : 2014/12/3
 Version : 0.5
 
The MIT License (MIT)

Copyright (c) 2014 DavidWTF

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.ComTypes;

namespace Kinect2
{
    namespace VGB
    {
        using WAITABLE_HANDLE = System.IntPtr;
        using TIMESPAN = System.Int64;
        using HRESULT = System.Int32;

        public class ContinuousGestureResult : BaseInterfaceWrap<IContinuousGestureResult>
        {
            public ContinuousGestureResult() : base() { }
            internal ContinuousGestureResult(IContinuousGestureResult arg) : base(arg) { }
            public float Progress
            {
                get { return GetMember<float>("Progress"); }
            }
        }
        public class DiscreteGestureResult : BaseInterfaceWrap<IDiscreteGestureResult>
        {
            public DiscreteGestureResult() : base() { }
            internal DiscreteGestureResult(IDiscreteGestureResult arg) : base(arg) { }
            public float Confidence
            {
                get { return GetMember<float>("Confidence"); }
            }
            public bool Detected
            {
                get { return GetMember<bool>("Detected"); }
            }
            public bool FirstFrameDetected
            {
                get { return GetMember<bool>("FirstFrameDetected"); }
            }
        }

        public class Gesture : BaseInterfaceWrap<IGesture>
        {
            public Gesture() : base() { }
            internal Gesture(IGesture arg) : base(arg) { }
            public GestureType GestureType
            {
                get { return GetMember<GestureType>("GestureType"); }
            }
            public string Name
            {
                get
                {
                    try
                    {
                        char[] filePath = new char[256];
                        origin.get_Name((uint)filePath.Length, filePath);
                        return new string(filePath);
                    }
                    catch { }
                    return null;
                }
            }
        }

        public class VisualGestureBuilderDatabase : BaseInterfaceWrap<IVisualGestureBuilderDatabase>
        {
            public VisualGestureBuilderDatabase() : base() { }
            internal VisualGestureBuilderDatabase(IVisualGestureBuilderDatabase arg) : base(arg) { }
            public VisualGestureBuilderDatabase(string fileName)
            {
                IVisualGestureBuilderDatabase instance = null;
                KinectVGB.CreateVisualGestureBuilderDatabaseInstanceFromFile(fileName, out instance);
                if (instance == null)
                    throw new NullReferenceException();
                origin = instance;
            }
            public VisualGestureBuilderDatabase(uint bufferSize, IntPtr bufferPtr)
            {
                IVisualGestureBuilderDatabase instance = null;
                KinectVGB.CreateVisualGestureBuilderDatabaseInstanceFromMemory(bufferSize, bufferPtr, out instance);
                if (instance == null)
                    throw new NullReferenceException();
                origin = instance;
            }
            public uint AvailableGesturesCount
            {
                get { return GetMember<uint>("AvailableGesturesCount"); }
            }
            public IList<Gesture> AvailableGestures
            {
                get
                {
                    try
                    {
                        uint count = origin.get_AvailableGesturesCount();
                        List<Gesture> list = new List<Gesture>((int)count);
                        IGesture[] availableGestures = new IGesture[(int)count];
                        origin.get_AvailableGestures(count, availableGestures);
                        for (uint i = 0; i < count; i++)
                            list.Add(new Gesture(availableGestures[i]));
                        return list;
                    }
                    catch { }
                    return null;
                }
            }
        }

        public class VisualGestureBuilderFrame : BaseInterfaceWrap<IVisualGestureBuilderFrame>
        {
            public VisualGestureBuilderFrame() : base() { }
            internal VisualGestureBuilderFrame(IVisualGestureBuilderFrame arg) : base(arg) { }
            public bool IsTrackingIdValid
            {
                get { return GetMember<bool>("IsTrackingIdValid"); }
            }
            public ulong TrackingId
            {
                get { return GetMember<ulong>("TrackingId"); }
            }
            public TimeSpan RelativeTime
            {
                get { return GetTimeSpan("RelativeTime"); }
            }
            class ContinuousGestureResultsDictionary : Dictionary<Gesture, ContinuousGestureResult>
            {
                IVisualGestureBuilderFrame frame;
                public ContinuousGestureResultsDictionary(IVisualGestureBuilderFrame frame)
                {
                    this.frame = frame;
                }
                public new ContinuousGestureResult this[Gesture key]
                {
                    get
                    {
                        try { return new ContinuousGestureResult(frame.get_ContinuousGestureResult((IGesture)key.Origin)); }
                        catch { }
                        return null;
                    }
                }
            }
            class DiscreteGestureResultsDictionary : Dictionary<Gesture, DiscreteGestureResult>
            {
                IVisualGestureBuilderFrame frame;
                public DiscreteGestureResultsDictionary(IVisualGestureBuilderFrame frame)
                {
                    this.frame = frame;
                }
                public new DiscreteGestureResult this[Gesture key]
                {
                    get
                    {
                        try { return new DiscreteGestureResult(frame.get_DiscreteGestureResult((IGesture)key.Origin)); }
                        catch { }
                        return null;
                    }
                }
            }
            public IDictionary<Gesture, ContinuousGestureResult> ContinuousGestureResults
            {
                get
                {
                    try { return new ContinuousGestureResultsDictionary(origin); }
                    catch { }
                    return null;
                }
            }
            public IDictionary<Gesture, DiscreteGestureResult> DiscreteGestureResults
            {
                get
                {
                    try { return new DiscreteGestureResultsDictionary(origin); }
                    catch { }
                    return null;
                }
            }
            public VisualGestureBuilderFrameSource VisualGestureBuilderFrameSource
            {
                get { return GetWrappedClass<VisualGestureBuilderFrameSource>("VisualGestureBuilderFrameSource"); }
            }
        }

        public class VisualGestureBuilderFrameSource : FrameSource<IVisualGestureBuilderFrameSource, VisualGestureBuilderFrameReader>
        {
            public VisualGestureBuilderFrameSource() : base() { }
            internal VisualGestureBuilderFrameSource(IVisualGestureBuilderFrameSource arg) : base(arg) { }
            public VisualGestureBuilderFrameSource(KinectSensor sensor, ulong initialTrackingId)
            {
                IVisualGestureBuilderFrameSource source = null;
                KinectVGB.CreateVisualGestureBuilderFrameSource((IKinectSensor)sensor.Origin, initialTrackingId, out source);
                if (source == null)
                    throw new NullReferenceException("IVisualGestureBuilderFrameSource");
                origin = source;
            }
            public void AddGesture(Gesture gesture)
            {
                try { origin.AddGesture((IGesture)gesture.Origin); }
                catch { }
            }
            public void AddGestures(IEnumerable<Gesture> gestures)
            {
                try
                {
                    List<IGesture> list = new List<IGesture>();
                    foreach (Gesture g in gestures)
                        list.Add((IGesture)g.Origin);
                    IGesture[] gestures2 = list.ToArray();
                    origin.AddGestures((uint)gestures2.Length, gestures2);
                }
                catch { }
            }
            public void RemoveGesture(Gesture gesture)
            {
                try { origin.RemoveGesture((IGesture)gesture.Origin); }
                catch { }
            }
            public bool GetIsEnabled(Gesture gesture)
            {
                try { return origin.GetIsEnabled((IGesture)gesture.Origin); }
                catch { }
                return false;
            }
            public void SetIsEnabled(Gesture gesture, bool isEnabled)
            {
                try { origin.SetIsEnabled((IGesture)gesture.Origin, isEnabled); }
                catch { }
            }
            public ICollection<Gesture> Gestures
            {
                get
                {
                    try
                    {
                        uint count = origin.get_GestureCount();
                        IGesture[] gestures = new IGesture[(int)count];
                        origin.get_Gestures(count, gestures);
                        List<Gesture> list = new List<Gesture>((int)count);
                        for (uint i = 0; i < count; i++)
                            list.Add(new Gesture(gestures[i]));
                        return new ReadOnlyCollection<Gesture>(list);
                    }
                    catch { }
                    return null;
                }
            }
            public bool HorizontalMirror
            {
                get { return GetMember<bool>("HorizontalMirror"); }
                set { PutMember<bool>("HorizontalMirror", value); }
            }
            public bool IsTrackingIdValid
            {
                get { return GetMember<bool>("IsTrackingIdValid"); }
            }
            public ulong TrackingId
            {
                get { return GetMember<ulong>("TrackingId"); }
                set { PutMember<ulong>("TrackingId", value); }
            }
        }

        public class VisualGestureBuilderFrameReference : FrameReference<IVisualGestureBuilderFrameReference, VisualGestureBuilderFrame>
        {
            public VisualGestureBuilderFrameReference() : base() { }
            public VisualGestureBuilderFrameReference(IVisualGestureBuilderFrameReference arg) : base(arg) { }
        }

        public class VisualGestureBuilderFrameArrivedEventArgs : FrameArrivedEventArgs<IVisualGestureBuilderFrameArrivedEventArgs, VisualGestureBuilderFrameReference>
        {
            public VisualGestureBuilderFrameArrivedEventArgs() : base() { }
            public VisualGestureBuilderFrameArrivedEventArgs(IVisualGestureBuilderFrameArrivedEventArgs arg) : base(arg) { }
        }

        public class VisualGestureBuilderFrameReader : FrameReader<IVisualGestureBuilderFrameReader, VisualGestureBuilderFrameArrivedEventArgs>
        {
            public VisualGestureBuilderFrameReader() : base() { }
            public VisualGestureBuilderFrameReader(IVisualGestureBuilderFrameReader arg) : base(arg) { }
            public VisualGestureBuilderFrameSource VisualGestureBuilderFrameSource
            {
                get { return GetWrappedClass<VisualGestureBuilderFrameSource>("VisualGestureBuilderFrameSource"); }
            }
            public VisualGestureBuilderFrame CalculateAndAcquireLatestFrame()
            {
                try { return new VisualGestureBuilderFrame(origin.CalculateAndAcquireLatestFrame()); }
                catch { }
                return null;
            }
        }
    }
}